home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-09-02 | 23.2 KB | 679 lines | [TEXT/CCL2] |
- ;;; View-Extensions.lisp
- ;;;
- ;;; This is a collection of classes and methods that extend the functionality of
- ;;; views in MCL 2.0. Some of the most useful extensions are the definition of
- ;;; relative position views which hopefully future versions of MCL will include,
- ;;; editable-number-dialog-item, and drag-view method.
- ;;;
- ;;; Address: Gordon Sawatzky
- ;;; National Research Council Canada
- ;;; 435 Ellice Avenue
- ;;; Winnipeg, MB R3B 1Y6
- ;;;
- ;;; This code is in the public domain and is distributed without warranty
- ;;; of any kind.
- ;;;
- ;;; Bug reports, comments, and suggestions should be sent to sawatzky@ciitip.ciit.ca
- ;;;
- ;;;
- ;;;
- ;;; The following is a brief description of all classes and methods contained in
- ;;; this file:
- ;;;
- ;;;
- ;;;
-
- ;;; o Simple view position methods to make code more readable
-
- ;;; (view-width (simple-view))
- ;;; (view-height (simple-view))
- ;;; (view-right (simple-view))
- ;;; (view-left (simple-view))
- ;;; (view-bottom (simple-view))
- ;;; (view-top (simple-view))
- ;;; (middle-left (simple-view))
- ;;; (middle-right (simple-view))
- ;;; (middle-top (simple-view))
- ;;; (middle-bottom (simple-view))
- ;;; (bottom-left (simple-view))
- ;;; (bottom-right (simple-view))
- ;;; (top-right (simple-view))
- ;;; (top-left (simple-view))
-
- ;;; o Simple point predicates for views
-
- ;;; (point-in-right-side-p (simple-view t))
- ;;; (point-in-left-side-p (simple-view t))
- ;;; (point-in-bottomright-p (simple-view t))
- ;;; (View-In-Rect (simple-view t))
- ;;; (View-partly-In-Rect (simple-view t))
-
-
- ;;; o Simple graphic methods for views to make code more readable
-
- ;;; (view-erase (simple-view))
- ;;; (view-frame (simple-view))
- ;;; (view-draw-vertical-line (simple-view t))
- ;;; (view-draw-horizontal-line (simple-view t))
- ;;; (view-invert (simple-view))
- ;;; (view-draw-corner-handles (simple-view))
- ;;; (view-draw-top-left-handle (simple-view))
- ;;; (view-draw-top-right-handle (simple-view))
- ;;; (view-draw-bottom-left-handle (simple-view))
- ;;; (view-draw-bottom-right-handle (simple-view))
- ;;; (view-draw-top-handle (simple-view))
- ;;; (view-draw-right-handle (simple-view))
- ;;; (view-draw-left-handle (simple-view))
- ;;; (view-draw-bottom-handle (simple-view))
-
-
-
- ;;; o Center view method, Relative views, drag-view-size and drag-view-position
-
- ;;; (center-view (simple-view))
- ;;; centered-text
- ;;; relative-view
- ;;; (object-source-code (dialog-item))
- ;;; relative-button
- ;;; relative-table
- ;;; (drag-view-position (simple-view view))
- ;;; (drag-view-size (simple-view view))
- ;;; (drag-rect (view))
-
- ;;; o Other views
-
- ;;; editable-number-dialog-item
- ;;; (dialog-item-number (editable-number-dialog-item))
- ;;; axis-view
- ;;; movable-dialog-item
-
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-
- (require 'QuickDraw)
-
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- ;;; Some interesting points of views
-
- (defmethod view-width ((view simple-view))
- (point-h (view-size view)))
-
- (defmethod view-height ((view simple-view))
- (point-v (view-size view)))
-
-
-
- (defmethod view-right ((view simple-view))
- (+ (point-h (view-position view))
- (point-h (view-size view))))
-
- (defmethod view-left ((view simple-view))
- (point-h (view-position view)))
-
-
- (defmethod view-bottom ((view simple-view))
- (+ (point-v (view-position view))
- (point-v (view-size view))))
-
- (defmethod view-top ((view simple-view))
- (point-v (view-position view)))
-
-
- (defmethod middle-left ((self simple-view))
- (let ((dp (view-position self)) (s (view-size self)))
- (make-point (point-h dp)
- (+ (point-v dp) (round (point-v s) 2)))))
-
-
- (defmethod middle-right ((self simple-view))
- (let ((dp (view-position self)) (s (view-size self)))
- (make-point (+ (point-h dp) (point-h s))
- (+ (point-v dp) (round (point-v s) 2)))))
-
-
- (defmethod middle-top ((self simple-view))
- (let ((dp (view-position self)) (s (view-size self)))
- (make-point (+ (point-h dp) (round (point-h s) 2))
- (point-v dp))))
-
-
- (defmethod middle-bottom ((self simple-view))
- (let ((dp (view-position self)) (s (view-size self)))
- (make-point (+ (point-h dp) (round (point-h s) 2))
- (+ (point-v dp) (point-v s)))))
-
-
- (defmethod bottom-left ((self simple-view))
- (let ((dp (view-position self)) (s (view-size self)))
- (make-point (point-h dp) (+ (point-v dp) (point-v s)))))
-
-
- (defmethod bottom-right ((self simple-view))
- (let ((dp (view-position self)) (s (view-size self)))
- (make-point (+ (point-h dp) (point-h s))
- (+ (point-v dp) (point-v s)))))
-
- (defmethod top-right ((self simple-view))
- (let ((dp (view-position self)) (s (view-size self)))
- (make-point (+ (point-h dp) (point-h s))
- (+ (point-v dp)))))
-
- (defmethod top-left ((self simple-view))
- (view-position self))
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;
- ;;; View position predicates
-
-
- (defmethod point-in-right-side-p ((self simple-view) p)
- (let ((dp (view-position self))
- (s (view-size self)))
- (rlet ((r :rect :left (+ (point-h dp) (round (point-h s) 2))
- :top (point-v dp)
- :right (+ (point-h dp) (point-h s))
- :bottom (+ (point-v dp) (point-v s))))
- (point-in-rect-p r p))))
-
- (defmethod point-in-left-side-p ((self simple-view) p)
- (let ((dp (view-position self))
- (s (view-size self)))
- (rlet ((r :rect :left (point-h dp)
- :top (point-v dp)
- :right (+ (point-h dp) (round (point-h s) 2))
- :bottom (+ (point-v dp) (point-v s))))
- (point-in-rect-p r p))))
-
-
-
- (defmethod point-in-bottomright-p ((self simple-view) p &optional (offset #@(10 10)))
- "Returns t if p of container is in bottomright of this view"
- (point-in-rect-p (make-record :rect
- :topleft (subtract-points
- (view-size self)
- offset)
- :bottomright (view-size self))
- (subtract-points p (view-position self))))
-
- (defmethod View-In-Rect ((self simple-view) rect)
- (and (point-in-rect-p rect (view-position self))
- (point-in-rect-p rect (add-points (view-position self)
- (view-size self)))))
-
- (defmethod View-partly-In-Rect ((self simple-view) rect)
- (or (point-in-rect-p rect (view-position self))
- (point-in-rect-p rect (top-right self))
- (point-in-rect-p rect (bottom-right self))
- (point-in-rect-p rect (bottom-left self))))
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;
- ;;; some simple graphic methods
- ;;;
-
- (defmethod view-erase ((view simple-view))
- (ccl::erase-rect view #@(0 0) (view-size view)))
-
- (defmethod view-frame ((view simple-view))
- (ccl::frame-rect view #@(0 0) (view-size view)))
-
- (defmethod view-draw-vertical-line ((view simple-view) h)
- (ccl::move-to view (make-point h 0))
- (ccl::line-to view (make-point h (view-height view))
- ))
-
- (defmethod view-draw-horizontal-line ((view simple-view) v)
- (ccl::move-to view (make-point 0 v))
- (ccl::line-to view (make-point (view-width view) v)
- ))
-
- (defmethod view-invert ((self simple-view))
- (ccl::invert-rect self #@(0 0) (view-size self)))
-
- (defvar *handle-size* 4)
-
- (defmethod view-draw-corner-handles ((self simple-view))
- (view-draw-top-left-handle self)
- (view-draw-top-right-handle self)
- (view-draw-bottom-left-handle self)
- (view-draw-bottom-right-handle self))
-
- (defmethod view-draw-top-left-handle ((self simple-view))
- (ccl::paint-rect self #@(0 0) (make-point *handle-size* *handle-size*)))
-
- (defmethod view-draw-top-right-handle ((self simple-view))
- (let ((r (point-h (view-size self))))
- (ccl::paint-rect self (make-point (- r *handle-size*) 0)
- (make-point r *handle-size*))))
-
- (defmethod view-draw-bottom-left-handle ((self simple-view))
- (let ((h (point-v (view-size self))))
- (ccl::paint-rect self (make-point 0 (- h *handle-size*))
- (make-point *handle-size* h))))
-
- (defmethod view-draw-bottom-right-handle ((self simple-view))
- (let ((r (point-h (view-size self)))
- (h (point-v (view-size self))))
- (ccl::paint-rect self (make-point (- r *handle-size*) (- h *handle-size*))
- (make-point r h))))
-
-
- (defmethod view-draw-top-handle ((self simple-view))
- (let ((r (point-h (view-size self))))
- (ccl::paint-rect self (make-point 0 0)
- (make-point r *handle-size*))))
-
- (defmethod view-draw-right-handle ((self simple-view))
- (let ((r (point-h (view-size self)))
- (h (point-v (view-size self))))
- (ccl::paint-rect self (make-point (- r *handle-size*) 0)
- (make-point r h))))
-
- (defmethod view-draw-left-handle ((self simple-view))
- (let ((h (point-v (view-size self))))
- (ccl::paint-rect self (make-point 0 0)
- (make-point *handle-size* h))))
-
- (defmethod view-draw-bottom-handle ((self simple-view))
- (let ((r (point-h (view-size self)))
- (h (point-v (view-size self))))
- (ccl::paint-rect self (make-point 0 (- h *handle-size*))
- (make-point r h))))
-
-
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- (defmethod center-view ((self simple-view))
- (when (view-container self)
- (cond ((> (view-width self) (view-width (view-container self)))
- (ed-beep) nil)
- (t
- (set-view-position self
- (make-point (floor (- (view-width (view-container self))
- (view-width self))
- 2)
- (point-v (view-position self))))
- (invalidate-view self)
- (view-draw-contents self)))))
-
- (defclass centered-text (static-text-dialog-item)
- ())
-
- (defmethod set-dialog-item-text :before ((self centered-text) text)
- (set-view-size self (make-point (+ (string-width text (view-font self)) 10)
- (view-height self)))
- (center-view self))
-
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- (defclass relative-view (simple-view)
- ((rel-position :initarg :rel-position :accessor rel-position :initform nil)
- (rel-size :initarg :rel-size :accessor rel-size :initform nil)))
-
-
- (defmethod set-view-container :before ((self relative-view) new-container)
- (when new-container
- (set-relative-view-size self new-container)))
-
- (defmethod set-relative-view-size ((self relative-view) container)
- (let ((current-position (if (view-position self)
- (view-position self) #@(0 0)))
- (current-size (if (view-size self)
- (view-size self) #@(30 12)))
- (container-width (view-width container))
- (container-height (view-height container)))
-
- (case (car (rel-position self))
- (nil nil)
- (:right (set-view-position self (- container-width
- (cadr (rel-position self))
- (point-h current-size))
- (point-v current-position)))
- (:left (set-view-position self (cadr (rel-position self))
- (point-v current-position)))
- (:top (set-view-position self (point-h current-position)
- (cadr (rel-position self))))
- (:bottom (set-view-position self (point-h current-position)
- (- container-height
- (cadr (rel-position self))
- (point-v current-size)))))
- (case (car (rel-size self))
- (nil nil)
- (:width (set-view-size self (- container-width
- (cadr (rel-size self)))
- (point-v current-size)))
- (:height (set-view-size self (point-h current-size)
- (- container-height
- (cadr (rel-size self)))))
- (:bottom-right-offset (set-view-size self
- (subtract-points
- (subtract-points (view-size container)
- (cadr (rel-size self)))
- current-position)))
- (:%width (set-view-size self (round (* container-width
- (cadr (rel-size self))))
- (point-v current-size)))
- (:%height (set-view-size self (point-h current-size)
- (round (* container-height
- (cadr (rel-size self))))))))
- ; (if (view-container self) (view-draw-contents self))
- )
-
- (defmethod set-view-size :after ((self view) h &optional v)
- (declare (ignore h v))
- (dolist (v (subviews self 'relative-view))
- (set-relative-view-size v self)))
-
-
-
- #| Change to IFT item-defs.lisp file to handle relative-views
-
- (defmethod object-source-code ((item dialog-item) &aux my-font)
- `(make-dialog-item ',(class-name (class-of item))
- ,(ppoint (view-position item))
- ,(ppoint (view-size item))
- ,(dialog-item-text item)
- ,(let* ((f (dialog-item-action-function item))
- (code (and (functionp f) (uncompile-function f))))
- (cond ((symbolp f) `,f)
- (code `#',code)
- (t nil)))
- ,@(let ((nick-name (view-nick-name item)))
- (and nick-name
- `(:view-nick-name ',nick-name)))
- ,@(cond ((typep item 'cl-user::relative-view)
- `(:rel-position ',(cl-user::rel-position item)
- :rel-size ',(cl-user::rel-size item)))
- (t nil))
- ,@(if (dialog-item-enabled-p item)
- ()
- '(:dialog-item-enabled-p nil))
- ,@(if (equal (setq my-font (view-font item))
- (window-font (view-window item)))
- ()
- `(:view-font ',my-font))
- ,@(let ((color-list (part-color-list item)))
- (and color-list
- `(:part-color-list ',color-list)))))
-
- |#
-
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;
- ;;; Some relative dialog items
- ;;;
- (defclass relative-button (button-dialog-item relative-view)
- ()
- (:documentation "A button whose position can be raltive to the container"))
-
- (defclass relative-table (sequence-dialog-item relative-view)
- ()
- (:documentation "A table whose position can be raltive to the container"))
-
- (defmethod set-relative-view-size :after ((self relative-table) container)
- (declare (ignore container))
- (set-cell-size self (- (view-width self) 15)
- (point-v (cell-size self))
- ))
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;
- ;;; Movable views
-
-
-
- (defmethod drag-view-position ((self simple-view) (container view) &optional other-views)
- (ccl::set-pen-mode container :patxor)
- (ccl::set-pen-pattern self *gray-pattern*)
- (let* ((size (view-size self))
- (view-pos (view-position self))
- (p1 (view-mouse-position container))
- (p2 p1)
- (delta #@(0 0))
- )
- (loop
- (setf p2 (view-mouse-position container))
- (cond ((mouse-down-p)
- (unless (= p1 p2)
- (frame-rect container (add-points view-pos delta)
- (add-points (add-points view-pos delta) size))
- (setf delta (add-points delta (subtract-points p2 p1)))
- (setf p1 p2)
- (frame-rect container (add-points view-pos delta)
- (add-points (add-points view-pos delta) size)))
- )
- (t (return t)))
- )
- (ccl::set-pen-pattern self *black-pattern*)
- (ccl::set-pen-mode container :patCopy)
- (unless (= delta #@(0 0))
- (set-view-position self (add-points view-pos delta))
- (dolist (v other-views)
- (set-view-position v (add-points (view-position v) delta)))))
- )
-
-
- (defmethod drag-view-size ((self simple-view) (container view))
-
- (let ((new-rect (drag-rect container (view-position self)
- (bottom-right self))))
- (cond ((empty-rect-p new-rect) nil)
- (t
- (if (= (view-position self) (rref new-rect :rect.topleft))
- nil (set-view-position self (rref new-rect :rect.topleft)))
- (set-view-size self (subtract-points (rref new-rect :rect.bottomright)
- (rref new-rect :rect.topleft)))
- ))
- (dispose-record new-rect))
- (view-draw-contents self))
-
-
-
-
- (defmethod drag-rect ((self view) &optional (start (view-mouse-position self))
- (pos (view-mouse-position self)))
- (ccl::set-pen-mode self :patxor)
- (ccl::set-pen-pattern self *gray-pattern*)
- (let ((rect (make-record :rect))
- p1 p2)
- (setf p1 (view-mouse-position self))
- (setf p2 p1)
- (loop
- (setf p2 (view-mouse-position self))
- (cond ((mouse-down-p)
- (unless (= p1 p2)
- (points-to-rect start pos rect)
- (frame-rect self rect)
- (setf pos (add-points pos (subtract-points p2 p1)))
- (setf p1 p2)
- (points-to-rect start pos rect)
- (frame-rect self rect))
- )
- (t (points-to-rect start pos rect)
- (frame-rect self rect)
- (return t)))
- )
-
- (ccl::set-pen-mode self :patCopy)
- (ccl::set-pen-pattern self *black-pattern*)
- (points-to-rect start pos rect)))
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;;
- ;;; Other dialog-items and views
-
-
- (defclass editable-number-dialog-item (editable-text-dialog-item)
- ((integer :initarg :integer :accessor integer :initform nil)
- (lower-bound :initarg :lower-bound :accessor lower-bound :initform nil)
- (upper-bound :initarg :upper-bound :accessor upper-bound :initform nil))
- (:documentation "Allows user to enter numbers (within a range) only"))
-
-
- (defmethod dialog-item-number ((self editable-number-dialog-item))
- (read-from-string (dialog-item-text self)))
-
- (defmethod exit-key-handler ((self editable-number-dialog-item)
- new-text-item)
- (declare (ignore new-text-item))
- (let ((integer (integer self))
- (lower-bound (lower-bound self))
- (upper-bound (upper-bound self))
- (thing (read-from-string (dialog-item-text self) nil nil))
- (message-position (local-to-global (view-window self)
- (add-points #@(5 10)
- (bottom-left self)))))
- (cond ((not (numberp thing))
- (message-dialog "This field must be a number !!"
- :size #@(150 80)
- :position message-position
- )
- nil)
- ((and lower-bound (< thing lower-bound))
- (message-dialog
- (format nil "This number must be >= ~D " lower-bound)
- :size #@(300 100)
- :position
- message-position)
- nil)
- ((and upper-bound (> thing upper-bound))
- (message-dialog
- (format nil "This number must be <= ~D " upper-bound)
- :size #@(300 100)
- :position
- message-position)
- nil)
- ((and integer (not (integerp thing)))
- (set-dialog-item-text self (format nil "~D" (floor thing)))
- t)
- (t t))))
-
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-
- (defclass axis-view (simple-view)
- ((orientation :initarg :orientation :accessor orientation :initform :vertical)
- (axis-length :initarg :axis-length :accessor axis-length :initform 100)
- (tick-length :initarg :tick-length :accessor tick-length :initform 5)
- (tick-spacing :initarg :tick-spacing :accessor tick-spacing :initform 10)
- ))
-
- (defmethod initialize-instance :after ((self axis-view) &rest initargs)
- (declare (ignore initargs))
- (if (equal (orientation self) :vertical)
- (set-view-size self (make-point (tick-length self) (1+ (axis-length self))))
- (set-view-size self (make-point (1+ (axis-length self)) (tick-length self)))))
-
- (defmethod view-draw-contents ((self axis-view) &aux (x 0) l)
- (cond ((equal (orientation self) :vertical)
- (view-draw-vertical-line self (round (view-width self) 2))
- (setf l (+ (view-height self) 1))
- (loop
- (view-draw-horizontal-line self x)
- (incf x (tick-spacing self))
- (if (>= x l) (return nil))))
- (t
- (view-draw-horizontal-line self (round (view-height self) 2))
- (setf l (+ (view-width self) 1))
- (loop
- (view-draw-vertical-line self x)
- (incf x (tick-spacing self))
- (if (>= x l) (return nil))))))
-
-
-
-
- (provide 'View-Extensions)
-
- #| Testing Stuff
-
-
- (setf w1 (make-instance 'window
- :view-position (make-point 520 100)))
-
-
- (make-instance 'axis-view
- :view-position #@(10 10)
- :orientation :horizontal
- :view-container w1)
-
- (defclass foo (relative-view) ())
-
- (defmethod view-draw-contents ((self foo))
- (view-erase self)
- (view-frame self)
- (move-to self #@(5 10))
- (princ "Relative View - Change Window Size" self))
-
- (make-instance 'foo
- :view-container w1
- :view-position (make-point 10 60)
- ; :rel-position '(:bottom 40)
- ; :rel-size '(:bottom 50)
- :rel-size '(:bottom-right-offset #@(100 50))
- :view-font '("Geneva" 9 :Plain)
- )
-
- (make-instance 'relative-button
- :dialog-item-text "BEEP"
- :dialog-item-action 'ed-beep
- :view-position #@(20 40)
- :rel-position '(:right 20)
- :view-container w1
- )
-
-
- (make-instance 'editable-number-dialog-item
- :view-size #@(40 18)
- :view-container w1
- :dialog-item-text "0"
- :lower-bound 0
- :upper-bound 10
- :integer t
- )
-
- (make-instance 'editable-number-dialog-item
- :view-size #@(40 18)
- :view-container w1
- :dialog-item-text "0"
- :lower-bound 0
- :integer t
- )
-
- (defclass movable-dialog-item (dialog-item) ())
-
- (defmethod view-click-event-handler ((self movable-dialog-item) p)
- (if (point-in-bottomright-p self p)
- (drag-view-size self (view-container self))
- (drag-view-position self (view-container self))))
-
- (defmethod view-draw-contents ((self movable-dialog-item))
- (view-erase self)
- (view-frame self)
- (move-to self #@(5 10))
- (princ "Click and Drag" self)
- (view-draw-bottom-right-handle self))
-
- (make-instance 'movable-dialog-item
- :view-size #@(40 20)
- :view-container w1
- :view-font '("Geneva" 9 :Plain))
-
- |#
-